package pl.umk.mat.fred.unicore.urc.storagemanagement.actions;

import java.io.BufferedInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.Arrays;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Random;
import java.util.UUID;

import org.apache.commons.httpclient.URIException;
import org.apache.commons.httpclient.util.URIUtil;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.SubProgressMonitor;
import org.eclipse.core.runtime.jobs.Job;
import org.eclipse.jface.action.Action;
import org.eclipse.jface.viewers.IStructuredSelection;
import org.eclipse.swt.SWT;
import org.eclipse.swt.widgets.FileDialog;
import org.eclipse.swt.widgets.Shell;
import org.eclipse.ui.PlatformUI;
import org.unigrids.services.atomic.types.ProtocolType;

import pl.umk.mat.fred.unicore.urc.storagemanagement.tools.StorageTools;
import pl.umk.mat.fred.unicore.urc.storagemanagement.tree.nodes.CatalogNode;
import pl.umk.mat.fred.unicore.urc.storagemanagement.tree.nodes.GridNode;
import pl.umk.mat.fred.unicore.urc.storagemanagement.tree.nodes.MultiplyCatalogNode;
import pl.umk.mat.fred.unicore.urc.storagemanagement.tree.nodes.Node;
import pl.umk.mat.fred.unicore.urc.storagemanagement.tree.nodes.StorageNode;
import pl.umk.mat.fred.unicore.urc.storagemanagement.unicore.Storage;
import pl.umk.mat.fred.unicore.urc.storagemanagement.views.StorageBrowserView;
import de.fzj.unicore.rcp.common.Constants;
import de.fzj.unicore.rcp.common.UnicoreCommonActivator;
import de.fzj.unicore.rcp.common.utils.ProgressListenerAdapter;
import de.fzj.unicore.rcp.common.utils.ProgressListeningInputStream;
import de.fzj.unicore.rcp.common.utils.UnicoreStorageTools;
import de.fzj.unicore.uas.client.FileTransferClient;
import de.fzj.unicore.uas.fts.ProgressListener;
import de.fzj.unicore.uas.fts.uftp.UFTPConstants;

public class SendLocalFilesAction extends Action {

	private StorageBrowserView view;
	private Shell shell;
	
	public SendLocalFilesAction(StorageBrowserView view) {
		this.view = view;
		this.setText("Send files");
	}
	
	public void run() {
		this.shell = PlatformUI.getWorkbench().getDisplay().getActiveShell();
		IStructuredSelection selection = (IStructuredSelection) view.getTreeViewer().getSelection();
		final FileDialog dialog = new FileDialog(shell, SWT.MULTI);
		String fn = dialog.open();
		Storage client = null;
		String path = null;
		Node node = null;
		if (selection.getFirstElement() instanceof StorageNode) {
			StorageNode n = (StorageNode) selection.getFirstElement();
			node = n;
			path = n.getPath();
			client = n.getStorage();
		} else if (selection.getFirstElement() instanceof CatalogNode) {
			CatalogNode n = (CatalogNode) selection.getFirstElement();
			node = n;
			path = n.getPath();
			client = n.getStorage();
		} else if (selection.getFirstElement() instanceof GridNode) {
			StorageNode n = StorageTools.randomStorageNode((GridNode)selection.getFirstElement());
			node = n;
			path = "/";
			client = n.getStorage();
		} else if (selection.getFirstElement() instanceof MultiplyCatalogNode) {
			CatalogNode cn = StorageTools.randomCatalogNode((MultiplyCatalogNode) selection.getFirstElement());
			node = cn;
			client = cn.getStorage();
			path = cn.getPath();
		}
		if (fn != null) {
			final Storage client2 = client;
			final String path2 = path;
			final Node node2 = node;
			Job job = new Job("Sending files") {
				@Override
				protected IStatus run(IProgressMonitor monitor) {
					Date start = new Date();
					monitor.beginTask("", dialog.getFileNames().length);
					for (String name : dialog.getFileNames()) {
						FileTransferClient ftClient = null;
						InputStream is = null;
						try {
							File file = new File(dialog.getFilterPath() + System.getProperty("file.separator") + name);
							ProtocolType.Enum protocol = StorageTools.getProtocol(file.length(), client2.getSupportedProtocols());
							String encodedPath = URIUtil.encode(path2 + "/" + name, org.apache.commons.httpclient.URI.allowed_fragment);
							Map<String,String> extraParameters = new HashMap<String, String>();
							StorageTools.provideParameters(extraParameters, protocol.toString());
							
							System.out.println("Fred " + protocol);
							System.out.println("Fred " + extraParameters);
							ftClient = client2.getImport(encodedPath, false, protocol, extraParameters);
							System.out.println("Fred client " + ftClient);
							
							SubProgressMonitor subMonitor = new SubProgressMonitor(monitor, (int) file.length());
							
							ProgressListener<Long> l = new ProgressListenerAdapter(subMonitor, file.length());
							subMonitor.beginTask("", 100);
							if (ftClient instanceof FileTransferClient.IMonitorable) {
								((FileTransferClient.IMonitorable) ftClient).setProgressListener(l);
								is = new BufferedInputStream(new FileInputStream(file));
							} else {
								is = new ProgressListeningInputStream(new BufferedInputStream(new FileInputStream(file)),l);
							}
							
							ftClient.writeAllData(is);
							monitor.worked(1);
							view.getDoubleClickAction().run(node2);
						} catch (URIException e) {
							e.printStackTrace();
						} catch (IOException e) {
							e.printStackTrace();
						} catch (Exception e) {
							e.printStackTrace();
						} finally {
							if (ftClient != null) {
								try {
									ftClient.destroy();
								} catch (Exception e) {
									e.printStackTrace();
								}
							}
							if (is != null) {
								try {
									is.close();
								} catch (IOException e) {
								}
							}
							if (monitor.isCanceled()) {
								return org.eclipse.core.runtime.Status.CANCEL_STATUS;
							}
						}
					}
					Date end = new Date();
					long tmp = end.getTime() - start.getTime();
					System.out.println("time " + tmp/60000 + ":" + (tmp%60000)/1000);
					return org.eclipse.core.runtime.Status.OK_STATUS;
				}
			};
			job.schedule();
		}
	}
}
